﻿using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using System.Threading;
using Microsoft.Win32.SafeHandles;
using WindowsAPI.PInvoke;
using WindowsAPI.Service;

namespace WindowsAPI
{
    /// <summary>Обёртка импортируемых функций библиотеки kernel32.dll</summary>
    [SuppressUnmanagedCodeSecurity, Dll(FileName)]
    public static partial class Kernel32
    {
        /* ------------------------------------------------------------------------------------------ */

        /// <summary>Имя файла библиотеки</summary>
        public const string FileName = "kernel32.dll";

        /* ------------------------------------------------------------------------------------------ */

        [DllImport(FileName)]
        public static extern bool IsBadCodePtr(IntPtr lpfn);

        [DllImport(FileName)]
        public static extern bool IsBadStringPtr(string lpsz, uint ucchMax);

        [DllImport(FileName)]
        public static extern bool IsBadWritePtr(IntPtr lp, uint ucb);

        [DllImport(FileName)]
        public static extern bool IsBadReadPtr(IntPtr lp, uint ucb);

        [DllImport(FileName, CharSet = CharSet.Auto)]
        public static extern bool GetComputerName([Out]StringBuilder buffer, int size);

        [DllImport(FileName, SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool GetComputerNameEx(COMPUTER_NAME_FORMAT NameType, [Out] StringBuilder lpBuffer, int lpnSize);

        [DllImport(FileName, CharSet = CharSet.Auto)]
        public static extern bool SetComputerName(string lpComputerName);

        [DllImport(FileName, SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool SetComputerNameEx(COMPUTER_NAME_FORMAT NameType, string lpBuffer);

        /// <summary>
        /// Функция  GetModuleHandle извлекает дескриптор указанного модуля, если файл был отображен в адресном 
        /// пространстве вызывающего процесса
        /// </summary>
        /// <param name="lpModuleName">Указатель на символьную строку с нулем в конце, которая содержит имя 
        /// модуля (или .dll или .exe файл). Если расширение имени файла опускается, в конец добавляется заданное по 
        /// умолчанию библиотечное расширение .dll. Символьная строка имени файла может включать в себя конечный 
        /// символ точки (.), который указывает, что имя модуля не имеет расширения. Строка не должна определять путь. 
        /// Когда определяется путь, убедитесь, что используются обратные слэши (\), а не прямые слэши (/). 
        /// Имя сравнивается (независимо от ситуации) с именами модулей в текущий момент отображаемыми в адресном 
        /// пространстве вызывающего процесса.</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - дескриптор указанного модуля</returns>
        [DllImport(FileName, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        //[DllImport(FileName, CharSet = CharSet.Auto, SetLastError = true)]
        //public static extern IntPtr GetModuleHandleEx(string lpModuleName);

        // This must be used if OSVERSIONINFO is defined as a struct or Class - The previous [In,Out] parameter defined for
        // a class could cause buffer overrun errors.
        [DllImport(FileName)]
        public static extern bool GetVersionEx(ref OSVERSIONINFO osvi);

        [DllImport(FileName, EntryPoint = "RtlZeroMemory", SetLastError = false)]
        public static extern void ZeroMemory(IntPtr dest, IntPtr size);

        [DllImport(FileName, SetLastError = false)]
        public static extern void RtlZeroMemory(IntPtr dest, IntPtr size);

        [DllImport(FileName)]
        public static extern uint GetTickCount();

        /// <summary>Установить локальное время</summary>
        /// <param name="lpLocalTime">Структура с информацией о времени</param>
        /// <returns>Истина, если функция завершилась успешно. Иначе - GetLastError()</returns>
        [DllImport(FileName, SetLastError = false)]
        public static extern bool SetLocalTime([In] ref SYSTEMTIME lpLocalTime);


        #region PE

        /// <summary>
        /// Функция отображает заданный исполняемый модуль в адресное пространство вызывающего процесса.
        /// </summary>
        /// <param name="lpFileName">Указатель на символьную строку с нулем в конце, которая именует исполняемый 
        /// модуль (или .dll или .exe файл). Указанное имя -  это имя файла модуля и оно не связано с именем самого 
        /// сохраняемого в библиотеке модуля, как это определено ключевым словом  LIBRARY в (.def) файле определения 
        /// модуля</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - дескриптор модуля</returns>
        [DllImport(FileName, SetLastError = true)]
        public extern static IntPtr LoadLibrary(string lpFileName);

        /// <summary>
        /// Функция  отображает указанный исполняемый модуль в адресное пространство вызывающего процесса. 
        /// Исполняемый модуль может быть .dll или .exe файл. Указанный модуль может заставить другие модули 
        /// отображаться в адресное пространство.
        /// </summary>
        /// <param name="lpFileName">Указатель на символьную строку с нулем в конце, которая именует исполняемый 
        /// модуль (или  .dll или  .exe файл). Указанное имя -  это имя файла исполняемого модуля. Это имя не связано 
        /// с именем самого сохраняемого в библиотеке модуля, как это определено ключевым словом  LIBRARY в (.def) 
        /// файле определения модуля</param>
        /// <param name="hFile">Этот параметр резервируется для будущего использования. Он должен быть ПУСТО (NULL).</param>
        /// <param name="dwFlags">Предпринимаемое действие при загрузке модуля. Если никакие флажки не устанавливаются,
        /// характер работы этой функции идентичен функции LoadLibrary. Этот параметр может быть одним из следующих
        /// значений.</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - дескриптор отображаемого исполняемого модуля</returns>
        [DllImport(FileName)]
        public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, LibraryFileInfo.API.LoadLibraryFlags dwFlags);

        /// <summary>
        /// Функция  уменьшает итоговое число ссылок на загруженные динамически подключаемые библиотеки (DLL). 
        /// Когда итоговое число ссылок достигает нуля, модуль отменяет отображение в адресном пространстве вызывающего 
        /// процесса, а дескриптор становится больше не допустим.
        /// </summary>
        /// <param name="hModule">Дескриптор загруженного DLL модуля</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение истина</returns>
        [DllImport(FileName, SetLastError = true)]
        public extern static bool FreeLibrary(IntPtr hModule);

        /// <summary>
        /// Функция извлекает адрес экспортируемой функции или переменной из заданной 
        /// динамически подключаемой библиотеки
        /// </summary>
        /// <param name="hModule">Дескриптор модуля DLL, который содержит функцию или переменную</param>
        /// <param name="procName">Указатель на символьную строку с нулем в конце, которая определяет 
        /// функцию или имя переменной, или порядковое значение функции. 
        /// Если этот параметр - порядковое значение, оно должно находиться в младшем слове; 
        /// старшее слово - должно быть нуль.</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - адрес экспортируемой функции или переменной</returns>
        [DllImport(FileName, SetLastError = true)]
        public extern static IntPtr GetProcAddress(IntPtr hModule, string procName);

        #endregion

        [DllImport(FileName, SetLastError = true)]
        public static extern uint GetCurrentThreadId();

        /// <summary>Функция закрывает дескриптор открытого объекта</summary>
        /// <param name="hObject">дескриптор объекта</param>
        /// <returns>Истина, если функция завершилась успешно.</returns>
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [DllImport(FileName, SetLastError = true), Link("http://vsokovikov.narod.ru/New_MSDN_API/Handles_objects/fn_closehandle.htm")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle([In] IntPtr hObject);

        /// <summary>Функция закрывает дескриптор открытого объекта</summary>
        /// <param name="hObject">дескриптор объекта</param>
        /// <returns>Истина, если функция завершилась успешно.</returns>
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [DllImport(FileName, SetLastError = true), Link("http://vsokovikov.narod.ru/New_MSDN_API/Handles_objects/fn_closehandle.htm")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle([In] SafeFileHandle hObject);

        [DllImport(FileName, SetLastError = true)]
        public static extern void GetSystemInfo([MarshalAs(UnmanagedType.Struct)] ref System_Info lpSystemInfo);

        [DllImport(FileName, SetLastError = true)]
        public static extern uint WinExec(string lpCmdLine, ShowWindowCommands uCmdShow);

        [DllImport(FileName, SetLastError = true)]
        public static extern uint GetSystemDirectory([Out] StringBuilder lpBuffer, uint uSize);

        [DllImport(FileName, SetLastError = true)]
        public static extern uint GetSystemWindowsDirectory([Out] StringBuilder lpBuffer, uint uSize);

        [DllImport(FileName, SetLastError = true)]
        public static extern uint GetWindowsDirectory([Out] StringBuilder lpBuffer, uint uSize);

        [DllImport(FileName, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);

        [DllImport(FileName, SetLastError = true)]
        public static extern IntPtr CreateRemoteThread(
            IntPtr hProcess,
            IntPtr lpThreadAttributes,
            uint dwStackSize, ThreadStart
            lpStartAddress,
            IntPtr lpParameter,
            uint dwCreationFlags,
            IntPtr lpThreadId);

        [DllImport(FileName, SetLastError = true)]
        public static extern IntPtr CommandLineToArgv(
            [MarshalAs(UnmanagedType.LPWStr)] 
            string lpCmdLine,
            out int pNumArgs);

        [DllImport(FileName, SetLastError = true)]
        public static extern IntPtr LocalFree(IntPtr hMem);

        [DllImport(FileName, SetLastError = true)]
        public static extern void GetStartupInfo(out StartupInfo lpStartupInfo);

        [DllImport(FileName, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.LPTStr)]
        public static extern string GetCommandLine();

        [DllImport(FileName, SetLastError = true)]
        public static extern IntPtr CreateToolhelp32Snapshot(SnapshotFlags dwFlags, uint th32ProcessID);

        [DllImport(FileName, SetLastError = true)]
        public static extern bool Process32First(IntPtr hSnapshot, ref ProcessEntry32 lppe);

        [DllImport(FileName, SetLastError = true)]
        public static extern bool Process32Next([In]IntPtr hSnapshot, ref ProcessEntry32 lppe);

        [DllImport(FileName, SetLastError = false)]
        public static extern IntPtr OpenProcess(
            ProcessAccessFlags dwDesiredAccess,
            [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
            int dwProcessId);

        [DllImport(FileName, SetLastError = false)]
        public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        /// <summary>Функция извлекает полный путь и имя указанного файла</summary>
        /// <param name="lpFileName">
        /// [in] Указатель на символьную строку с нулем в конце, которая определяет допустимое имя файла. 
        /// Эта символьная строка может использовать или короткие, или длинные имена файла
        /// </param>
        /// <param name="nBufferLength">[in] Размер буфера для приема строки с нулем в конце для  диска и пути</param>
        /// <param name="lpBuffer">[out] Указатель на буфер, который получает символьную строку с нулем в конце для диска и пути</param>
        /// <param name="lpFilePart">[out] Указатель на буфер, который получает адрес (в lpBuffer) имени заключающего файла, как составляющей части в строке пути</param>
        /// <returns>Если функция завершается успешно, возвращаемое значение - длина символьной строки</returns>
        [Obsolete("Use System.IO.Path.GetFullPath(filename)")]
        [DllImport(FileName, SetLastError = false)]
        public static extern uint GetFullPathName(string lpFileName, int nBufferLength,
           [Out] StringBuilder lpBuffer, [Out] StringBuilder lpFilePart);

        /*
         * // Define a virtual drive
         * VolumeFunctions.DefineDosDevice(0, @"Y:", @"c:\test\folder\name\");
         *
         * // Delete a virtual drive. The drive letter and folder must match.
         * VolumeFunctions.DefineDosDevice(
         *    VolumeFunctions.DDD_REMOVE_DEFINITION + VolumeFunctions.DDD_EXACT_MATCH_ON_REMOVE, 
         *    @"Y:", 
         *    @"C:\test\folder\name");
         *
         * // Delete if you know only the drive letter.
         * DeleteVolumeMountPoint(@"Y:\");
         * public const uint DDD_RAW_TARGET_PATH = 0x00000001;
         * public const uint DDD_REMOVE_DEFINITION = 0x00000002;
         * public const uint DDD_EXACT_MATCH_ON_REMOVE = 0x00000004;
         * public const uint DDD_NO_BROADCAST_SYSTEM = 0x00000008;
         */
        [DllImport(FileName, SetLastError = false)]
        public static extern bool DefineDosDevice(uint dwFlags, string lpDeviceName, string lpTargetPath);

        [DllImport(FileName, SetLastError = false)]
        public static extern uint QueryDosDevice(string lpDeviceName, IntPtr lpTargetPath, uint ucchMax);

        [DllImport(FileName, SetLastError = false)]
        public static extern uint QueryDosDevice([In] string lpDeviceName, [Out]StringBuilder lpTargetPath, [In] int ucchMax);

        //private static string[] QueryDosDevice()
        //{
        //    // Allocate some memory to get a list of all system devices.
        //    // Start with a small size and dynamically give more space until we have enough room.
        //    var returnSize = 0;
        //    var maxSize = 100u;
        //    string[] retval = null;

        //    while(returnSize == 0)
        //    {
        //        var mem = Marshal.AllocHGlobal(maxSize);
        //        if(mem == IntPtr.Zero)
        //            throw new OutOfMemoryException();

        //        // mem points to memory that needs freeing
        //        try
        //        {
        //            returnSize = QueryDosDevice(null, mem, maxSize);
        //            if(returnSize != 0)
        //            {
        //                var allDevices = Marshal.PtrToStringAnsi(mem, returnSize);
        //                retval = allDevices.Split('\0');
        //                break; // not really needed, but makes it more clear...
        //            }
        //            else if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
        //            //maybe better
        //            //else if( Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
        //            //ERROR_INSUFFICIENT_BUFFER = 122;
        //            {
        //                maxSize *= 10;
        //            }
        //            else
        //            {
        //                Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
        //            }
        //        }
        //        finally
        //        {
        //            Marshal.FreeHGlobal(mem);
        //        }
        //    }
        //    return retval;
        //}


        //private static string GetRealPath(string path)
        //{
        //    var pathInformation = new StringBuilder(Consts.MAX_PATH);

        //    // Get the drive letter of the 
        //    var driveLetter = System.IO.Path.GetPathRoot(path).Replace("\\", "");
        //    QueryDosDevice(driveLetter, pathInformation, 250);

        //    // If drive is substed, the result will be in the format of "\??\C:\RealPath\".
        //    if(!pathInformation.ToString().Contains("\\??\\"))
        //        return path;

        //    // Strip the \??\ prefix.
        //    var realRoot = pathInformation.ToString().Remove(0, 4);

        //    //Combine the paths.
        //    string realPath = System.IO.Path.Combine(realRoot, path.Replace(System.IO.Path.GetPathRoot(path), ""));
        //    return realPath;
        //}

        // static extern uint GetLogicalDriveStrings(uint nBufferLength, 
        //    [Out] StringBuilder lpBuffer); --- Don't do this!

        // if we were to use the StringBuilder, only the first string would be returned
        // so, since arrays are reference types, we can pass an array of chars
        // just initialize it prior to call the function as
        // char[] lpBuffer = new char[nBufferLength];
        [DllImport(FileName, SetLastError = false)]
        public static extern bool GetLogicalDriveStrings(uint nBufferLength, [Out] char[] lpBuffer);

        // DeleteVolumeMountPoint(DriveLetter+":\\");
        [DllImport(FileName, SetLastError = false)]
        public static extern bool DeleteVolumeMountPoint(string lpszVolumeMountPoint);

        [DllImport(FileName, SetLastError = false)]
        public static extern bool SetHandleInformation(IntPtr hObject, HANDLE_FLAGS dwMask, HANDLE_FLAGS dwFlags);

        [DllImport(FileName, SetLastError = false)]
        public static extern bool GetHandleInformation(IntPtr hObject, out HANDLE_FLAGS lpdwFlags);

        [DllImport(FileName, SetLastError = true)]
        public static extern SafeProcessHandle OpenProcess(
            [In] ProcessAccessTypes dwDesiredAccess,
            [In, MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
            [In] int dwProcessId);

        /// <summary>
        /// Функция делает копию дескриптора объекта. 
        /// Продублированный дескриптор относится к тому же самому объекту, что и исходный дескриптор. 
        /// Поэтому, любое изменение объекта отражается через оба дескриптора. 
        /// Например, дескриптор файла, зарегистрированный для текущего файла, 
        /// является всегда одним и тем же для обоих дескрипторов.
        /// </summary>
        /// <param name="hSourceProcessHandle">дескриптор процесса - источника</param>
        /// <param name="hSourceHandle">дубликат дескриптора</param>
        /// <param name="hTargetProcessHandle">дескриптор целевого процесса</param>
        /// <param name="lpTargetHandle">дубликат дескриптора</param>
        /// <param name="dwDesiredAccess">запрос доступа</param>
        /// <param name="bInheritHandle">параметр наследования дескриптора</param>
        /// <param name="dwOptions">необязательные действия</param>
        /// <returns>Истина, если функция завершилась успшно. Иначе GetLastError().</returns>
        [DllImport(FileName, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool DuplicateHandle(
            [In] IntPtr hSourceProcessHandle,                          // дескриптор процесса - источника
            [In] IntPtr hSourceHandle,                                 // дубликат дескриптора
            [In] IntPtr hTargetProcessHandle,                          // дескриптор целевого процесса
            [Out] out SafeObjectHandle lpTargetHandle,                 // дубликат дескриптора
            [In] int dwDesiredAccess,                                  // запрос доступа
            [In, MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,   // параметр наследования дескриптора
            [In] DuplicateHandleOptions dwOptions);                    // необязательные действия

        [DllImport(FileName)]
        public static extern IntPtr GetCurrentProcess();

        [DllImport(FileName, SetLastError = true)]
        public static extern int GetProcessId([In] IntPtr Process);

        [DllImport(FileName, SetLastError = true)]
        public static extern bool CreateProcess(
                    string lpApplicationName,
                    string lpCommandLine,
                    ref SECURITY_ATTRIBUTES lpProcessAttributes,
                    ref SECURITY_ATTRIBUTES lpThreadAttributes,
                    bool bInheritHandles,
                    uint dwCreationFlags,
                    IntPtr lpEnvironment,
                    string lpCurrentDirectory,
                    [In] ref STARTUPINFO lpStartupInfo,
                    out PROCESS_INFORMATION lpProcessInformation);

        [DllImport(FileName, SetLastError = true)]
        public static extern bool CreateDirectory(string lpPathName, SECURITY_ATTRIBUTES lpSecurityAttributes);

        [DllImport(FileName, SetLastError = true, CharSet = CharSet.Auto)]
        public static extern void GetStartupInfo(out STARTUPINFO lpStartupInfo);

        [DllImport(FileName, SetLastError = true), UsedIn(typeof(WaitableTimer))]
        public static extern WaitForSingleObjectResult WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);

        [DllImport(FileName, SetLastError = true), UsedIn(typeof(WaitableTimer))]
        public static extern IntPtr CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, string lpTimerName);

        [DllImport(FileName, SetLastError = true), UsedIn(typeof(WaitableTimer))]
        [Link("http://uinc.ru/articles/38/")]
        public static extern bool SetWaitableTimer(
                    IntPtr hTimer,
                    [In] ref long pDueTime,
                    int lPeriod,
                    Action pfnCompletionRoutine,
                    IntPtr lpArgToCompletionRoutine,
                    bool fResume);

        [DllImport(FileName, SetLastError = true), UsedIn(typeof(WaitableTimer))]
        public static extern bool CancelWaitableTimer(IntPtr hTimer);

        [DllImport(FileName, ExactSpelling = true)]
        public static extern IntPtr GlobalAlloc(int flags, int size);
        [DllImport(FileName, ExactSpelling = true)]
        public static extern IntPtr GlobalLock(IntPtr handle);
        [DllImport(FileName, ExactSpelling = true)]
        public static extern bool GlobalUnlock(IntPtr handle);
        [DllImport(FileName, ExactSpelling = true)]
        public static extern IntPtr GlobalFree(IntPtr handle);

        [DllImport(FileName, SetLastError = false)]
        public static extern void RtlMoveMemory(IntPtr dest, IntPtr src, int size);

        [DllImport(FileName, SetLastError = false)]
        public static extern bool SetSystemTimeAdjustment(uint dwTimeAdjustment, bool bTimeAdjustmentDisabled);

        [DllImport(FileName, SetLastError = false)]
        public static extern bool SetSystemTime([In] ref SYSTEMTIME time);

        [DllImport(FileName, SetLastError = false)]
        public static extern TimeZoneResult GetTimeZoneInformation(out TIME_ZONE_INFORMATION lpTimeZoneInformation);


    }

    [Serializable]
    public enum COMPUTER_NAME_FORMAT
    {
        ComputerNameNetBIOS,
        ComputerNameDnsHostname,
        ComputerNameDnsDomain,
        ComputerNameDnsFullyQualified,
        ComputerNamePhysicalNetBIOS,
        ComputerNamePhysicalDnsHostname,
        ComputerNamePhysicalDnsDomain,
        ComputerNamePhysicalDnsFullyQualified
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct TIME_ZONE_INFORMATION
    {
        [MarshalAs(UnmanagedType.I4)]
        public int Bias;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string StandardName;

        public SYSTEMTIME StandardDate;

        [MarshalAs(UnmanagedType.I4)]
        public int StandardBias;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
        public string DaylightName;

        public SYSTEMTIME DaylightDate;

        [MarshalAs(UnmanagedType.I4)]
        public int DaylightBias;
    }

    [Serializable]
    public enum TimeZoneResult : uint
    {
        Unknown = 0,
        Standard = 1,
        Daylight = 2,
        Invalid = 0xFFFFFFFF,
    }

    /// <summary>API структура с информацией о времениs</summary>
    [StructLayout(LayoutKind.Sequential), Serializable]
    public struct SYSTEMTIME
    {
        /// <summary>Месяц</summary>
        [Serializable]
        public enum MonthType : uint
        {
            /// <summary>Январь</summary>
            January = 1,
            /// <summary>Февраль</summary>
            February = 2,
            /// <summary>Март</summary>
            March = 3,
            /// <summary>Апрель</summary>
            April = 4,
            /// <summary>Май</summary>
            May = 5,
            /// <summary>Июнь</summary>
            June = 6,
            /// <summary>Июль</summary>
            July = 7,
            /// <summary>Август</summary>
            August = 8,
            /// <summary>Сентябрь</summary>
            September = 9,
            /// <summary>Октябрь</summary>
            October = 10,
            /// <summary>Нояюрь</summary>
            November = 11,
            /// <summary>Декабрь</summary>
            December = 12
        }

        /// <summary>День недели</summary>
        [Serializable]
        public enum DayOfWeekType : uint
        {
            /// <summary>Воскресенье</summary>
            Sunday = 1,
            /// <summary>Понедельник</summary>
            Monday = 2,
            /// <summary>Вторник</summary>
            Tuesday = 3,
            /// <summary>Среда</summary>
            Wednesday = 4,
            /// <summary>Четверг</summary>
            Thursday = 5,
            /// <summary>Пятница</summary>
            Friday = 6,
            /// <summary>Суббота</summary>
            Saturday = 7
        }

        /// <summary>Год</summary>
        public ushort Year;
        /// <summary>Месяц</summary>
        public MonthType Month;
        /// <summary>Дeнь недели</summary>
        public DayOfWeekType DayOfWeek;
        /// <summary>День</summary>
        public ushort Day;
        /// <summary>Час</summary>
        public ushort Hour;
        /// <summary>Минута</summary>
        public ushort Minute;
        /// <summary>Секунда</summary>
        public ushort Second;
        /// <summary>Миллисекунда</summary>
        public ushort Milliseconds;

        /// <summary>Инициализация новой API структуры времени системы</summary>
        /// <param name="time">Структура времени</param>
        public SYSTEMTIME(DateTime time)
        {
            Year = (ushort)time.Year;
            Month = (MonthType)time.Month;
            DayOfWeek = (DayOfWeekType)time.DayOfWeek;
            Day = (ushort)time.Day;
            Hour = (ushort)time.Hour;
            Minute = (ushort)time.Minute;
            Second = (ushort)time.Second;
            Milliseconds = (ushort)time.Millisecond;
        }

        /// <summary>Преобарзование API структуры времени системы в структуру времени</summary>
        /// <returns></returns>
        public DateTime ToDateTime() { return new DateTime(Year, (int)Month, Day, Hour, Minute, Second, Milliseconds); }

        /// <summary>Оператор неявного приведения API структуры времени системы в структуру времени</summary>
        /// <param name="time">API структура времени системы</param><returns>Структура времени</returns>
        public static implicit operator DateTime(SYSTEMTIME time) { return time.ToDateTime(); }

        /// <summary>ОПератор неявного приведения структуры времени в API структуру времени системы</summary>
        /// <param name="time">Структура времени</param>
        /// <returns>API-структура времени системы</returns>
        public static implicit operator SYSTEMTIME(DateTime time) { return new SYSTEMTIME(time); }
    }

    // Use this when the unmanaged API expects the structure passed by-value, or 
    // or if you want to pass it by-reference as a pointer to a structure
    [StructLayout(LayoutKind.Sequential)]
    public struct OSVERSIONINFO
    {
        public int dwOSVersionInfoSize;
        public uint dwMajorVersion;
        public uint dwMinorVersion;
        public uint dwBuildNumber;
        public VER_PLATFORM dwPlatformId;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public string szCSDVersion;
        public short wServicePackMajor;
        public short wServicePackMinor;
        public short wSuiteMask;
        public byte wProductType;
        public byte wReserved;
        public static OSVERSIONINFO Default { get { return new OSVERSIONINFO { dwOSVersionInfoSize = Marshal.SizeOf(typeof(OSVERSIONINFO)) }; } }
    }

    public enum VER_PLATFORM : uint { WIN32_NT = 2 }

    public enum WaitForSingleObjectResult : uint
    {
        WAIT_OBJECT_0 = 0x00000000,
        WAIT_ABANDONED = 0x00000080,
        WAIT_TIMEOUT = 0x00000102
    }

    /// <summary>Структура информации о процессе</summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        /// <summary>Указатель на процесс</summary>
        public IntPtr hProcess;
        /// <summary>Указатель на поток</summary>
        public IntPtr hThread;
        /// <summary>Идентификатор процесса</summary>
        public int dwProcessId;
        /// <summary>Идентификатор потока</summary>
        public int dwThreadId;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct STARTUPINFO
    {
        public int cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public int dwX;
        public int dwY;
        public int dwXSize;
        public int dwYSize;
        public int dwXCountChars;
        public int dwYCountChars;
        public int dwFillAttribute;
        public int dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public int nLength;
        public IntPtr lpSecurityDescriptor;
        public int bInheritHandle;
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public struct USB_ROOT_HUB_NAME
    {
        public int ActualLength;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Consts.BUFFER_SIZE)]
        public string RootHubName;
    }
}
